package com.example.webchar.webchar.config;


import com.example.webchar.webchar.mapper.slave.UserMapperSlave;
import com.example.webchar.webchar.pojo.Users;
import com.example.webchar.webchar.utils.JwtUtil;
import com.example.webchar.webchar.utils.JwtToken;
import com.example.webchar.webchar.utils.RedisUtils;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.servlet.http.HttpServletRequest;
import java.util.Collections;

/**
 * 授权和认证
 *
 * @program: boot
 * @description
 * @author: 毛叶柜子
 * @create: 2021-03-24 12:06
 **/
@Slf4j
@Service
public class MyRealm extends AuthorizingRealm {

    @Autowired
    private RedisUtils redisUtils;
    @Autowired
    private UserMapperSlave userMapperSlave;

    @Autowired
    public MyRealm() {
        super();
    }

    @Autowired
    private HttpServletRequest request;

    /**
     * 大坑！，必须重写此方法，不然Shiro会报错
     */
    @Override
    public boolean supports(AuthenticationToken token) {
        return token instanceof JwtToken;
    }

    /**
     * 认证.登录
     *
     * @param auth
     * @return
     */
    @SneakyThrows
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken auth) {
        String token = (String) auth.getCredentials();
        if (redisUtils.get(token) == null) {
            throw new Exception("令牌无效");
        } else {
            redisUtils.expire(token, 60 * 30);
            //在token还没过期的时候访问到了 更新
            return new SimpleAuthenticationInfo(token, token, "MyRealm");
        }
    }

    /**
     * @param principal
     * @return 授权存在安全隐患 如果登录后 一直访问授权字段，
     * 授权中的token是登录的token
     * 导致 在进入授权后 请求头token可有可无
     */
    @SneakyThrows
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principal) {
        SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
        String token = JwtUtil.subStringToken(request);
        Users user = (Users) redisUtils.get(token);
        //获取user信息
        try {
            Integer roseId = userMapperSlave.queryRoseId(user.getId());
            String roseName = userMapperSlave.queryRoseName(roseId);
            if (roseName != null) {
                info.setRoles(Collections.singleton(roseName));
                log.info("user信息为" + user);
                log.info("该类的权限Id为" + roseId);
                log.info("当前账号的rose为" + roseName);
            }
        } catch (Exception e) {
            throw new Exception("授权失败");
        }
        return info;
    }

}


